from app import api_base as api
from app.user.models import Role, Permission
from app.user.serializers.role import RoleSerializer
from exlib.flask_restplus.resource import ListResource, SingleResource
from exlib.flask_restplus.reqparse import RequestParser
from exlib.webbase.response import FailedResponse
from utils import pagination, get_object_or_404
from utils.decorators import marshal_item, marshal_table
from utils.perm import perm_required


class RoleView(SingleResource):
    model_class = Role
    model_serializer = RoleSerializer

    @perm_required('user.role', 'view')
    @marshal_item(RoleSerializer)
    def get(self, id):
        obj = get_object_or_404(self.model_class, id=id)
        return RoleSerializer(obj).item()

    poster = RequestParser()
    poster.add_argument('name', type=str, required=False, store_missing=False, help='权限名')
    poster.add_argument('desc', type=str, required=False, store_missing=False, help='补充说明')
    poster.add_argument('permissions', location='json', type=list, required=False, store_missing=False, help='权限id')

    @perm_required('user.role', 'edit')
    @api.expect(poster)
    @marshal_item(RoleSerializer)
    def put(self, id):
        obj = get_object_or_404(self.model_class, id=id)
        args = self.poster.parse_args()
        permissions = args.pop("permissions", None)
        try:
            if permissions:
                permission_list = Permission.objects(id__in=permissions)
                if not len(permissions) == len(permission_list): return FailedResponse(message="permissions不存在")
        except:
            return FailedResponse(message="permissions不规范")

        if args:
            obj.modify(**args)

        if permissions is not None:
            obj.set_permissions(permissions)

        return RoleSerializer(obj).item(
            message=self.msg_edit_success
        )

    @perm_required('user.role', 'delete')
    @marshal_item(RoleSerializer)
    def delete(self, id):
        obj = get_object_or_404(self.model_class, id=id)
        obj.is_deleted = True
        obj.save()
        return RoleSerializer(obj).item(
            message=self.msg_del_success
        )


class RolesView(ListResource):
    model_class = Role
    model_serializer = RoleSerializer

    filter = RequestParser()
    filter.add_argument('id', dest='id', type=str, required=False, store_missing=False, help='user id')

    @perm_required('user.role', 'view')
    @api.expect(pagination, filter)
    @marshal_table(RoleSerializer)
    def get(self):
        args = self.filter.parse_args()
        objs = Role.objects.filter(**args)
        pargs = pagination.parse_args()
        res = self.order_paginate(objs, pargs)
        permissions_ids = set([])
        for role in res:
            for p in role._permissions:
                permissions_ids.add(p)
        permissions_data = {p.id: p for p in Permission.objects(id__in=list(permissions_ids))}
        for role in res:
            role.set_cached_property('permissions', [permissions_data[p] for p in role._permissions])
        return RoleSerializer(res).table(
            total=objs.count(),
            pargs=pargs
        )

    poster = RequestParser()
    poster.add_argument('name', type=str, required=True, help='role name')
    poster.add_argument('key', type=str, required=True, help='role key')
    poster.add_argument('desc', type=str, required=False, store_missing=False, help='role description')
    poster.add_argument('permissions', location='json', type=list, required=False, store_missing=False, help='权限id')

    @perm_required('user.role', 'add')
    @api.expect(poster)
    @marshal_item(RoleSerializer)
    def post(self):
        args = self.poster.parse_args()
        permissions = args.pop("permissions", None)
        try:
            if permissions:
                permission_list = Permission.objects(id__in=permissions)
                if not len(permissions) == len(permission_list): return FailedResponse(message="permissions不存在")
        except:
            return FailedResponse(message="permissions不规范")

        obj = self.model_class(**args)
        obj.save()
        if permissions is not None:
            obj.set_permissions(permissions)
        return RoleSerializer(obj).item(
            message=self.msg_add_success
        )
